package gsolver;

import org.apache.commons.math.genetics.SelectionPolicy;
import org.apache.commons.math.genetics.Chromosome;
import org.apache.commons.math.genetics.ChromosomePair;
import org.apache.commons.math.genetics.Population;

import java.util.Random;
import java.util.Arrays;
import java.util.AbstractMap;
import java.util.Comparator;

import gsolver.GPopulation;
import gsolver.GPopulation.PaireFitnessCumuleeChromosome;

/**
 * Algorithme de séléction d'un couple de solutions pour
 * le croisement et la mutation avec roulette.
 */
public class GSelectionRoulette implements SelectionPolicy {
    private Random rand;

    public GSelectionRoulette(Random rand) {
	this.rand = rand;
    }

    /**
     * Sélectionne deux individus par roulette avec remise.
     */
    public ChromosomePair select(Population population) {
	return new ChromosomePair(select1((GPopulation)population), 
				  select1((GPopulation)population));
    }

    /**
     * Sélectionne un individu par roulette avec remise.
     */
    private Chromosome select1(GPopulation population) {
	PaireFitnessCumuleeChromosome[] sommeFitness = population.getSommeFitness();
	double aTrouver = rand.nextDouble() * 
	    sommeFitness[sommeFitness.length - 1].fitnessCumulee;
	int index = 
	    Arrays.binarySearch(sommeFitness, new PaireFitnessCumuleeChromosome(aTrouver, null));
	
	if (index < 0) {
	    return sommeFitness[-index - 1].chromosome;
	} else {
	    return sommeFitness[index].chromosome;
	}
    }
}